<?php

/**
 * LaFabbrica.org
 *
 * @author Gigi Pastore (gigi@la-fabbrica.org)
 * @package    LaFabbrica
 * @copyright  Copyright (c) 2011 Luigi Pastore
 * @created  14-apr-2011
 */
class Classes_Core_Application
{

    //public $module = 'default';

    private $_registeredModules = array( );
    private $_module;
    private $_controller;
    private $_action;
    private $_params = array( );
    /**
     * Singleton instance
     *
     * @var Layout
     */
    protected static $_instance = null;

    public function __construct()
    {
	/**
	 * Eseguiamo automaticamente tutti i metodi che iniziano con 'init'
	 */
	$class_methods = get_class_methods( $this );

	foreach( $class_methods as $method_name )
	{
	    if( 'init' === substr( $method_name, 0, 4 ) AND $method_name !== 'init' )
	    {
		$this->$method_name();
	    }
	}
	/**
	 * Registra i Moduli
	 */
	$this->registerModules();

	/**
	 * Settiamo la richiesta
	 */
	$this->setRequest();

    }

    /**
     * Ritorna istanza di Layout
     *
     * Implementazione del Singleton pattern
     *
     * @return Layout Provides a fluent interface
     */
    public static function getInstance()
    {
	if( null === self::$_instance )
	{
	    self::$_instance = new self();
	}

	return self::$_instance;
    }

    /**
     * Inizializza Moduli
     */
    private function initDb()
    {
	$this->db = Classes_Core_MysqliLayer::getInstance();
    }

    private function initLayout()
    {
	$this->layout = Classes_Core_Layout::getInstance();
    }

    private function initErrorHandler()
    {
	$error_handler = new Classes_Core_Exceptions;

	set_error_handler( array( $error_handler, 'error' ) );
	set_exception_handler( array( $error_handler, 'exception' ) );
    }

    private function initConstants()
    {
	$ini_array = parse_ini_file( APPLICATION_PATH . '/config/costanti.ini' );

	foreach( $ini_array as $key => $value )
	    define( strtoupper( $key ), $value );
    }

    private function initConfigs()
    {
	$configs_ini = parse_ini_file( APPLICATION_PATH . '/config/config.ini' );

	foreach( $configs_ini as $key => $value )
	    define( strtoupper( $key ), $value );
    }

    private function initSession()
    {
	session_start();
    }
    
    private function initResources()
    {
//	$this->_resource['Province'] = array(
//	    '1' => array( 'short_name' => 'AG', 'long_name' => 'Agrigento' ),
//	    '2' => array( 'short_name' => 'AL', 'long_name' => 'Alessandria' ),
//	    '3' => array( 'short_name' => 'AN', 'long_name' => 'Ancona' ),
//	    '4' => array( 'short_name' => 'AQ', 'long_name' => 'Aquila' ),
//	    '5' => array( 'short_name' => 'AR', 'long_name' => 'Arezzo' ),
//	    '6' => array( 'short_name' => 'AP', 'long_name' => 'Ascoli Piceno' ),
//	    '7' => array( 'short_name' => 'AT', 'long_name' => 'Asti' ),
//	    '8' => array( 'short_name' => 'AV', 'long_name' => 'Avellino' ),
//	    '9' => array( 'short_name' => 'BA', 'long_name' => 'Bari' ),
//	    '10' => array( 'short_name' => 'BT', 'long_name' => 'Barletta Andria Trani' ),
//	    '11' => array( 'short_name' => 'BL', 'long_name' => 'Belluno' ),
//	    '12' => array( 'short_name' => 'BN', 'long_name' => 'Benevento' ),
//	    '13' => array( 'short_name' => 'BG', 'long_name' => 'Bergamo' ),
//	    '14' => array( 'short_name' => 'BI', 'long_name' => 'Biella' ),
//	    '15' => array( 'short_name' => 'BO', 'long_name' => 'Bologna' ),
//	    '16' => array( 'short_name' => 'BZ', 'long_name' => 'Bolzano' ),
//	    '17' => array( 'short_name' => 'BS', 'long_name' => 'Brescia' ),
//	    '18' => array( 'short_name' => 'BR', 'long_name' => 'Brindisi' ),
//	    '19' => array( 'short_name' => 'CA', 'long_name' => 'Cagliari' ),
//	    '20' => array( 'short_name' => 'CL', 'long_name' => 'Caltanissetta' ),
//	    '21' => array( 'short_name' => 'CB', 'long_name' => 'Campobasso' ),
//	    '22' => array( 'short_name' => 'CI', 'long_name' => 'Carbonia-Iglesias' ),
//	    '23' => array( 'short_name' => 'CE', 'long_name' => 'Caserta' ),
//	    '24' => array( 'short_name' => 'CT', 'long_name' => 'Catania' ),
//	    '25' => array( 'short_name' => 'CZ', 'long_name' => 'Catanzaro' ),
//	    '26' => array( 'short_name' => 'CH', 'long_name' => 'Chieti' ),
//	    '27' => array( 'short_name' => 'CO', 'long_name' => 'Como' ),
//	    '28' => array( 'short_name' => 'CS', 'long_name' => 'Cosenza' ),
//	    '29' => array( 'short_name' => 'CR', 'long_name' => 'Cremona' ),
//	    '30' => array( 'short_name' => 'KR', 'long_name' => 'Crotone' ),
//	    '31' => array( 'short_name' => 'CN', 'long_name' => 'Cuneo' ),
//	    '32' => array( 'short_name' => 'EN', 'long_name' => 'Enna' ),
//	    '33' => array( 'short_name' => 'FM', 'long_name' => 'Fermo' ),
//	    '34' => array( 'short_name' => 'FE', 'long_name' => 'Ferrara' ),
//	    '35' => array( 'short_name' => 'FI', 'long_name' => 'Firenze' ),
//	    '36' => array( 'short_name' => 'FG', 'long_name' => 'Foggia' ),
//	    '37' => array( 'short_name' => 'FC', 'long_name' => 'Forlì-Cesena' ),
//	    '38' => array( 'short_name' => 'FR', 'long_name' => 'Frosinone' ),
//	    '39' => array( 'short_name' => 'GE', 'long_name' => 'Genova' ),
//	    '40' => array( 'short_name' => 'GO', 'long_name' => 'Gorizia' ),
//	    '41' => array( 'short_name' => 'GR', 'long_name' => 'Grosseto' ),
//	    '42' => array( 'short_name' => 'IM', 'long_name' => 'Imperia' ),
//	    '43' => array( 'short_name' => 'IS', 'long_name' => 'Isernia' ),
//	    '44' => array( 'short_name' => 'LT', 'long_name' => 'Latina' ),
//	    '45' => array( 'short_name' => 'LE', 'long_name' => 'Lecce' ),
//	    '46' => array( 'short_name' => 'LC', 'long_name' => 'Lecco' ),
//	    '47' => array( 'short_name' => 'LI', 'long_name' => 'Livorno' ),
//	    '48' => array( 'short_name' => 'LO', 'long_name' => 'Lodi' ),
//	    '49' => array( 'short_name' => 'LU', 'long_name' => 'Lucca' ),
//	    '50' => array( 'short_name' => 'MC', 'long_name' => 'Macerata' ),
//	    '51' => array( 'short_name' => 'MN', 'long_name' => 'Mantova' ),
//	    '52' => array( 'short_name' => 'MS', 'long_name' => 'Massa-Carrara' ),
//	    '53' => array( 'short_name' => 'MT', 'long_name' => 'Matera' ),
//	    '54' => array( 'short_name' => 'VS', 'long_name' => 'Medio Campidano' ),
//	    '55' => array( 'short_name' => 'ME', 'long_name' => 'Messina' ),
//	    '56' => array( 'short_name' => 'MI', 'long_name' => 'Milano' ),
//	    '57' => array( 'short_name' => 'MO', 'long_name' => 'Modena' ),
//	    '58' => array( 'short_name' => 'MB', 'long_name' => 'Monza e della Brianza' ),
//	    '59' => array( 'short_name' => 'NA', 'long_name' => 'Napoli' ),
//	    '60' => array( 'short_name' => 'NO', 'long_name' => 'Novara' ),
//	    '61' => array( 'short_name' => 'NU', 'long_name' => 'Nuoro' ),
//	    '62' => array( 'short_name' => 'OG', 'long_name' => 'Ogliastra' ),
//	    '63' => array( 'short_name' => 'OT', 'long_name' => 'Olbia-Tempio' ),
//	    '64' => array( 'short_name' => 'OR', 'long_name' => 'Oristano' ),
//	    '65' => array( 'short_name' => 'PD', 'long_name' => 'Padova' ),
//	    '66' => array( 'short_name' => 'PA', 'long_name' => 'Palermo' ),
//	    '67' => array( 'short_name' => 'PR', 'long_name' => 'Parma' ),
//	    '68' => array( 'short_name' => 'PV', 'long_name' => 'Pavia' ),
//	    '69' => array( 'short_name' => 'PG', 'long_name' => 'Perugia' ),
//	    '70' => array( 'short_name' => 'PU', 'long_name' => 'Pesaro e Urbino' ),
//	    '71' => array( 'short_name' => 'PE', 'long_name' => 'Pescara' ),
//	    '72' => array( 'short_name' => 'PC', 'long_name' => 'Piacenza' ),
//	    '73' => array( 'short_name' => 'PI', 'long_name' => 'Pisa' ),
//	    '74' => array( 'short_name' => 'PT', 'long_name' => 'Pistoia' ),
//	    '75' => array( 'short_name' => 'PN', 'long_name' => 'Pordenone' ),
//	    '76' => array( 'short_name' => 'PZ', 'long_name' => 'Potenza' ),
//	    '77' => array( 'short_name' => 'PO', 'long_name' => 'Prato' ),
//	    '78' => array( 'short_name' => 'RG', 'long_name' => 'Ragusa' ),
//	    '79' => array( 'short_name' => 'RA', 'long_name' => 'Ravenna' ),
//	    '80' => array( 'short_name' => 'RC', 'long_name' => 'Reggio Calabria' ),
//	    '81' => array( 'short_name' => 'RE', 'long_name' => 'Reggio Emilia' ),
//	    '82' => array( 'short_name' => 'RI', 'long_name' => 'Rieti' ),
//	    '83' => array( 'short_name' => 'RN', 'long_name' => 'Rimini' ),
//	    '84' => array( 'short_name' => 'RM', 'long_name' => 'Roma' ),
//	    '85' => array( 'short_name' => 'RO', 'long_name' => 'Rovigo' ),
//	    '86' => array( 'short_name' => 'SA', 'long_name' => 'Salerno' ),
//	    '87' => array( 'short_name' => 'SS', 'long_name' => 'Sassari' ),
//	    '88' => array( 'short_name' => 'SV', 'long_name' => 'Savona' ),
//	    '89' => array( 'short_name' => 'SI', 'long_name' => 'Siena' ),
//	    '90' => array( 'short_name' => 'SR', 'long_name' => 'Siracusa' ),
//	    '91' => array( 'short_name' => 'SO', 'long_name' => 'Sondrio' ),
//	    '92' => array( 'short_name' => 'SP', 'long_name' => 'Spezia' ),
//	    '93' => array( 'short_name' => 'TA', 'long_name' => 'Taranto' ),
//	    '94' => array( 'short_name' => 'TE', 'long_name' => 'Teramo' ),
//	    '95' => array( 'short_name' => 'TR', 'long_name' => 'Terni' ),
//	    '96' => array( 'short_name' => 'TO', 'long_name' => 'Torino' ),
//	    '97' => array( 'short_name' => 'TP', 'long_name' => 'Trapani' ),
//	    '98' => array( 'short_name' => 'TN', 'long_name' => 'Trento' ),
//	    '99' => array( 'short_name' => 'TV', 'long_name' => 'Treviso' ),
//	    '100' => array( 'short_name' => 'TS', 'long_name' => 'Trieste' ),
//	    '101' => array( 'short_name' => 'UD', 'long_name' => 'Udine' ),
//	    '102' => array( 'short_name' => 'AO', 'long_name' => 'Valle d\'Aosta' ),
//	    '103' => array( 'short_name' => 'VA', 'long_name' => 'Varese' ),
//	    '104' => array( 'short_name' => 'VE', 'long_name' => 'Venezia' ),
//	    '105' => array( 'short_name' => 'VB', 'long_name' => 'Verbano Cusio Ossola' ),
//	    '106' => array( 'short_name' => 'VC', 'long_name' => 'Vercelli' ),
//	    '107' => array( 'short_name' => 'VR', 'long_name' => 'Verona' ),
//	    '108' => array( 'short_name' => 'VV', 'long_name' => 'Vibo Valentia' ),
//	    '109' => array( 'short_name' => 'VI', 'long_name' => 'Vicenza' ),
//	    '110' => array( 'short_name' => 'VT', 'long_name' => 'Viterbo' ),
//	);
	
	$this->_resource['ContactRoles'] = array(
	    1 => 'Proprietario/Presidente',
	    'Gestore',
	    'Direttore Artistico',
	    'Fonico',
	    'Promoter',
            'Addetto Stampa',
            'Altro'
	);

	$this->_resource['PartnerTypes'] = array(
	    1 => 'Agenzia di Booking',
	    'Agenzia di Management',
	    'Press Agency',
	    'Etichetta',
            'Rivenditore',
            'Altro'
	);
	
	$this->_resource['Days'] = array(
	    1 => 'Lun',
	    'Mar',
	    'Mer',
	    'Gio',
	    'Ven',
	    'Sab',
	    'Dom'
	);
	
	$this->_resource['Months'] = array(
	    1 => 'Gen',
	    'Feb',
	    'Mar',
	    'Apr',
            'Mag',
	    'Giu',
	    'Lug',
	    'Ago',
	    'Set',
	    'Ott',
	    'Nov',
	    'Dic'
	);
	
	$this->_resource['MonthsFull'] = array(
	    1 => 'Gennaio',
	    'Febbraio',
	    'Marzo',
	    'Aprile',
            'Maggio',
	    'Giugno',
	    'Luglio',
	    'Agosto',
	    'Settembre',
	    'Ottobre',
	    'Novembre',
	    'Dicembre'
	);
    }

    private function initAuth()
    {
	$this->authModel = new Classes_Core_Auth;
	list( $this->auth->status, $this->auth->user, $this->auth->session_id ) = $this->authModel->getStatus();
    }

    /**
     * Esegue il routing della richiesta
     * 
     * Se $request[1] == 'admin' (es: http://url.tld/admin/etc..) -> Amministrazione
     * altrimenti esegui routing
     */
    public function run()
    {

	$this->layout->module = $this->getModule();
	$this->layout->controller = $this->getController();
	$this->layout->action = $this->getAction();
	$this->layout->params = $this->getParams();

	require_once APPLICATION_PATH . '/modules/' . $this->_module . '/Router.php';

	$router = new Router();
	$router->route();

	echo $this->layout->display( $this->_module );
    }

    /**
     * Registra i Moduli, prendendo i nomi delle directory in ./modules
     */
    private function registerModules()
    {
	$d = dir( APPLICATION_PATH . '/modules' );

	while( false !== ($entry = $d->read()) )
	    if( $entry != '.' AND $entry != '..' )
		$this->_registeredModules[] = $entry;

	$d->close();
    }

    /**
     * Ottiene i parametri della richiesta dall'Url separando
     * le richieste Ajax dalle richieste standard.
     * In caso di richiesta Ajax aggiunge il parametro 'section'
     * 
     * ATTENZIONE!
     * Currently, this header ('XMLHttpRequest') is known to be passed by default with the following JS libraries: 
     * - Prototype and Scriptaculous (and libraries derived from Prototype)
     * - Yahoo! UI Library
     * - jQuery
     * - MochiKit
     * 
     * @return array Array nella forma array( 0 => 'modulo', 1 => ecc...)
     */


    private function setRequest()
    {
	$urlParams = $this->parseRequest();

	# Controlla che il modulo sia registrato altrimenti rimanda al default
	if( $urlParams[1] == '' OR !in_array( $urlParams[1], $this->_registeredModules ) )
	{
	    $this->_module = 'default';
	    $request[0] = $this->_module;
	    $request = array_merge( $request, $urlParams );
	}
	else
	{
	    $this->_module = $urlParams[1];
	    for( $i = 1; $i <= count( $urlParams ); $i++ )
	    {
		$request[$i - 1] = $urlParams[$i];
	    }
	}

	$this->_controller = $request[1];
	$this->_action = $request[2];

	if( $this->isXmlHttpRequest() === false )
	{
	    for( $i = 3; $i <= count( $request ) - 1; $i++ )
	    {
		if( $request[$i] != '' AND $request[$i + 1] != '' )
		    $this->_params[$request[$i]] = $request[$i + 1];

		$i++;
	    }
	}
	else
	{
            /**
             * In caso di ricerca la gestione dei parametri è diversa...
             * La richiesta viene indirizzata all'action search del controller Search.
             */
            if( $request[1] == 'search' )
            {
                $this->_controller              = $request[1];
                $this->_action                  = 'search';
                $this->_params['section']       = $request[2];
                $this->_params['searchString']  = $request[3];

                for( $i = 4; $i <= count( $request ) - 1; $i++ )
                {
                    if( $request[$i] != '' AND $request[$i + 1] != '' )
                        $this->_params[$request[$i]] = $request[$i + 1];

                    $i++;
                }
            }
            else
            {
                $this->_params['section'] = $request[3];

                for( $i = 4; $i <= count( $request ) - 1; $i++ )
                {
                    if( $request[$i] != '' AND $request[$i + 1] != '' )
                        $this->_params[$request[$i]] = $request[$i + 1];

                    $i++;
                }	    
            }
	}
	
	// Mini-implementazione dell'ECGP
	if( $_GET )
	    foreach( $_GET AS $k => $v )
		$this->_params[$k] = $_GET[$k];

	if( $_POST )
	    foreach( $_POST AS $k => $v )
		$this->_params[$k] = $_POST[$k];
    }

    private function parseRequest()
    {
	$parse = parse_url( BASE_URL . $_SERVER['REQUEST_URI'] );
	$parts = explode( '/', $parse['path'] );

	unset( $parts[0] );

	return $parts;
    }

    /**
     * Return the value of the given HTTP header. Pass the header name as the
     * plain, HTTP-specified header name. Ex.: Ask for 'Accept' to get the
     * Accept header, 'Accept-Encoding' to get the Accept-Encoding header.
     *
     * @param string $header HTTP header name
     * @return string|false HTTP header value, or false if not found
     * @throws Zend_Controller_Request_Exception
     */
    public function getHeader($header)
    {
        if( empty( $header ) )
	{
	    throw new Classes_Exceptions( 'An HTTP header name is required' );
	}

        // Try to get it from the $_SERVER array first
        $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
        if (!empty($_SERVER[$temp])) {
            return $_SERVER[$temp];
        }

        // This seems to be the only way to get the Authorization header on
        // Apache
        if (function_exists('apache_request_headers')) {
            $headers = apache_request_headers();
            if (!empty($headers[$header])) {
                return $headers[$header];
            }
        }

        return false;
    }    
    
    /**
     * Is the request a Javascript XMLHttpRequest?
     *
     * Should work with Prototype/Script.aculo.us, possibly others.
     *
     * @return boolean
     */
    public function isXmlHttpRequest()
    {
        return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
    }    
    
    public function getModule()
    {
	return $this->_module ? $this->_module : 'default';
    }

    public function getController()
    {
	return $this->_controller ? $this->_controller : 'index';
    }

    public function getAction()
    {
	return $this->_action ? $this->_action : 'index';
    }

    /**
     * Get an action parameter
     *
     * @param string $key
     * @param mixed $default Default value to use if key not found
     * @return mixed
     */
    public function getParam( $key, $default = null )
    {
	$key = (string) $key;
	if( isset( $this->_params[$key] ) )
	{
	    return $this->_params[$key];
	}

	return $default;
    }

    /**
     * Get all action parameters
     *
     * @return array
     */
    public function getParams()
    {
	return $this->_params;
    }

    public function getResource( $resource )
    {
	if( is_null( $this->_resource[$resource] ) )
	    throw new Classes_Exceptions( 'Risorsa ' . $resource . ' sconosciuta' );

	return $this->_resource[$resource];
    }

}

